/**
 * 视频采集控制器模块
 */
module controller.CollectController;

import std.typecons : Tuple;
import core.thread : Thread;
import core.time : msecs;

import vibe.data.json : Json;
import vibe.http.server : HTTPServerRequest, HTTPServerResponse;

import model.Teleplay;
import model.TeleplayVlink;
import model.Movie;
import model.MovieVlink;
import model.Animation;
import model.AnimationVlink;
import repository.TeleplayRepo;
import repository.TeleplayLinksRepo;
import repository.MovieRepo;
import repository.MovieLinksRepo;
import repository.AnimationRepo;
import repository.AnimationLinksRepo;
import utils.VideoCollect;
import utils.RespData;
import utils.ObjMapping : ObjMapping;
import utils.SecurityVerification : signValidator;

import std.stdio;

TeleplayRepo _tRepo; // 电视剧仓储
TeleplayLinksRepo _tlRepo; // 电视剧视频链接仓储
MovieRepo _mRepo; // 电影仓储
MovieLinksRepo _mlRepo; // 电影视频链接仓储
AnimationRepo _aRepo; // 动漫仓储
AnimationLinksRepo _alRepo; // 动漫视频链接仓储

static this ()
{
    _tRepo = new TeleplayRepo();
    _tlRepo = new TeleplayLinksRepo();
    _mRepo = new MovieRepo();
    _mlRepo = new MovieLinksRepo();
    _aRepo = new AnimationRepo();
    _alRepo = new AnimationLinksRepo();
}

static ~this ()
{
    destroy(_tRepo);
    destroy(_tlRepo);
    destroy(_mRepo);
    destroy(_mlRepo);
    destroy(_aRepo);
    destroy(_alRepo);
}

/** 
* 视频信息采集
*/
void collect (HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.array : split;

    // 接收前端数据,反序列化
    Json json = req.json;
    string cate = json["cate"].to!string();
    Json urls = json["urls"];
    string sign = json["sign"].to!string();

    // 判空
    if (sign == "" || cate == "" || urls.length == 0)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    import std.format : format;

    string reqParamsStr = format("%s%s", cate, urls.length);
    if (!signValidator(reqParamsStr, sign))
    {
        resp.writeJsonBody(RespData.newData(403, "签名不正确！"), 403);
        return;
    }

    // 网络视频信息采集工作
    switch (cate)
    {
    case "电视剧":
        foreach (url; urls)
        {
            Tuple!(TeleplayDtoFromCreate, TeleplayVlinkDtoFromCreate[]) teleplay = VideoCollect.getTeleplayInfo(
                url.to!string());
            TeleplayDtoFromCreate teleplayInfo = teleplay[0];
            TeleplayVlinkDtoFromCreate[] teleplayLinks = teleplay[1];
            if (teleplayInfo is null || teleplayLinks is null)
            {
                continue;
            }
            bool res1 = _tRepo.addTeleplay(ObjMapping.mappingToObject!(Teleplay, TeleplayDtoFromCreate)(
                    teleplayInfo));
            if (!res1)
            {
                continue;
            }
            // 转换为实体对象
            TeleplayVlink[] tls = [];
            foreach (ref tl; teleplayLinks)
            {
                tls ~= ObjMapping.mappingToObject!(TeleplayVlink, TeleplayVlinkDtoFromCreate)(tl);
            }
            // 批量添加视频链接
            _tlRepo.addTeleplayLinkBatch(tls);

            // // 逐一添加
            // foreach (ref tvdfc; teleplayLinks)
            // {
            //     TeleplayVlink tv = ObjMapping.mappingToObject!(TeleplayVlink, TeleplayVlinkDtoFromCreate)(
            //         tvdfc);
            //     // 逐一添加
            //     bool res = _tlRepo.addTeleplayLink2(tv);
            //     if (!res) // 失败，退出
            //     {
            //         break;
            //     }
            // }

            Thread.sleep(300.msecs);
        }
        break;
    case "电影":
        foreach (ref url; urls)
        {
            Tuple!(MovieDtoFromCreate, MovieVlinkDtoFromCreate[]) movie = VideoCollect.getMovieInfo(
                url.to!string());
            MovieDtoFromCreate movieInfo = movie[0];
            MovieVlinkDtoFromCreate[] movieLinks = movie[1];
            if (movieInfo is null || movieLinks is null)
            {
                continue;
            }
            bool res1 = _mRepo.addMovie(ObjMapping.mappingToObject!(Movie, MovieDtoFromCreate)(
                    movieInfo));
            if (!res1)
            {
                continue;
            }

            // 转换为实体对象
            MovieVlink[] mls = [];
            foreach (ref ml; movieLinks)
            {
                mls ~= ObjMapping.mappingToObject!(MovieVlink, MovieVlinkDtoFromCreate)(ml);
            }
            // 批量添加视频链接
            _mlRepo.addMovieLinkBatch(mls);

            Thread.sleep(300.msecs);
        }
        break;
    case "动漫":
        foreach (ref url; urls)
        {
            Tuple!(AnimationDtoFromCreate, AnimationVlinkDtoFromCreate[]) animation = VideoCollect.getAnimationInfo(
                url.to!string());
            AnimationDtoFromCreate animationInfo = animation[0];
            AnimationVlinkDtoFromCreate[] animationLinks = animation[1];
            if (animationInfo is null || animationLinks is null)
            {
                continue;
            }
            bool res1 = _aRepo.addAnimation(ObjMapping.mappingToObject!(Animation, AnimationDtoFromCreate)(
                    animationInfo));
            if (!res1)
            {
                continue;
            }
            // 转换为实体对象
            AnimationVlink[] aLinks = [];
            foreach (ref al; animationLinks)
            {
                aLinks ~= ObjMapping.mappingToObject!(AnimationVlink, AnimationVlinkDtoFromCreate)(
                    al);
            }

            // 批量添加视频链接
            _alRepo.addAnimationLinkBatch(aLinks);

            // // 逐一添加
            // foreach (ref avdfc; animationLinks)
            // {
            //     // 转换为实体对象
            //     AnimationVlink av = ObjMapping.mappingToObject!(AnimationVlink, AnimationVlinkDtoFromCreate)(
            //         avdfc);
            //     // 逐一添加
            //     bool res = _alRepo.addAnimationLink2(av);
            //     if (!res) // 失败，退出
            //     {
            //         break;
            //     }
            // }

            Thread.sleep(300.msecs);
        }
        break;
    default:
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    resp.writeJsonBody(RespData.newData(200, "完成"));
}
